package com.authority.framework.config.shiro;

import com.authority.framework.online.dao.OnlineSessionDAO;
import com.authority.framework.online.dao.OnlineSessionFactory;
import com.authority.framework.online.session.OnlineWebSessionManager;
import com.authority.framework.online.session.SpringSessionValidationScheduler;
import com.authority.framework.online.LogoutFilter;
import com.authority.framework.online.filter.OnlineSessionFilter;
import com.authority.framework.online.filter.SyncOnlineSessionFilter;
import com.authority.framework.web.domain.SysMenuEntity;
import com.authority.framework.web.service.SysMenuService;
import com.authority.framework.base.util.StringUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {

	// 登录地址
	@Value("${shiro.user.loginUrl}")
	private String loginUrl;

	// 密码加密方式
	@Value("${shiro.user.hashAlgorithmName}")
	private String hashAlgorithmName;
	// 密码加密次数
	@Value("${shiro.user.hashIterations}")
	private Integer hashIterations;

	// 相隔多久检查一次session的有效性，单位毫秒，默认就是10分钟
	@Value("${shiro.session.validationInterval}")
	private int validationInterval;

	// Session超时时间，单位为毫秒（默认30分钟）
	@Value("${shiro.session.expireTime}")
	private int expireTime;

	@Autowired
	private SysMenuService sysMenuService;


	@Bean(name = "realm")
	@DependsOn("lifecycleBeanPostProcessor")
	@ConditionalOnMissingBean
	public Realm realm() {
		MyRealm myRealm = new MyRealm();
		return myRealm;
	}

	/**
	 * 用户授权信息Cache
	 */
	@Bean(name = "shiroCacheManager")
	@ConditionalOnMissingBean
	public CacheManager cacheManager() {
		return new MemoryConstrainedCacheManager();
	}
/*
	@Bean(name = "securityManager")
	@ConditionalOnMissingBean
	public DefaultSecurityManager securityManager() {
		DefaultSecurityManager sm = new DefaultWebSecurityManager();
		sm.setCacheManager(cacheManager());
		return sm;
	}*/



	/**
	 * 自定义sessionDAO会话
	 */
	@Bean
	public OnlineSessionDAO sessionDAO()
	{
		OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
		return sessionDAO;
	}

	/**
	 * 自定义sessionFactory会话
	 */
	@Bean
	public OnlineSessionFactory sessionFactory()
	{
		OnlineSessionFactory sessionFactory = new OnlineSessionFactory();
		return sessionFactory;
	}

	/**
	 * 自定义sessionFactory调度器
	 */
	@Bean
	public SpringSessionValidationScheduler sessionValidationScheduler()
	{
		SpringSessionValidationScheduler sessionValidationScheduler = new SpringSessionValidationScheduler();
		// 相隔多久检查一次session的有效性，单位毫秒，默认就是10分钟
		sessionValidationScheduler.setSessionValidationInterval(validationInterval * 60 * 1000);
		// 设置会话验证调度器进行会话验证时的会话管理器
		sessionValidationScheduler.setSessionManager(sessionValidationManager());
		return sessionValidationScheduler;
	}


	/**
	 * 会话管理器
	 */
	@Bean
	public OnlineWebSessionManager sessionValidationManager()
	{
		OnlineWebSessionManager manager = new OnlineWebSessionManager();

		// 删除过期的session
		manager.setDeleteInvalidSessions(true);
		// 设置全局session超时时间
		manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
		// 去掉 JSESSIONID
		manager.setSessionIdUrlRewritingEnabled(false);
		// 是否定时检查session
		manager.setSessionValidationSchedulerEnabled(true);
		// 自定义SessionDao
		manager.setSessionDAO(sessionDAO());
		// 自定义sessionFactory
		manager.setSessionFactory(sessionFactory());
		return manager;
	}

	/**
	 * 会话管理器
	 */
	@Bean
	public OnlineWebSessionManager sessionManager()
	{
		OnlineWebSessionManager manager = new OnlineWebSessionManager();
	/*	// 加入缓存管理器
		manager.setCacheManager(getEhCacheManager());*/
		// 删除过期的session
		manager.setDeleteInvalidSessions(true);
		// 设置全局session超时时间
		manager.setGlobalSessionTimeout(expireTime * 60 * 1000);
		// 去掉 JSESSIONID
		manager.setSessionIdUrlRewritingEnabled(false);
		// 定义要使用的无效的Session定时调度器
		manager.setSessionValidationScheduler(sessionValidationScheduler());
		// 是否定时检查session
		manager.setSessionValidationSchedulerEnabled(true);
		// 自定义SessionDao
		manager.setSessionDAO(sessionDAO());
		// 自定义sessionFactory
		manager.setSessionFactory(sessionFactory());
		return manager;
	}

	/**
	 * 安全管理器
	 */
	@Bean
	public SecurityManager securityManager(Realm userRealm)
	{
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 设置realm.
		securityManager.setRealm(userRealm);
		/*// 记住我
		securityManager.setRememberMeManager(rememberMeManager());*/
		// 注入缓存管理器;
	/*	securityManager.setCacheManager(getEhCacheManager());*/
		// session管理器
		securityManager.setSessionManager(sessionManager());
		return securityManager;
	}

	// 密码加密
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName(hashAlgorithmName);//散列算法:MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512等。
		hashedCredentialsMatcher.setHashIterations(hashIterations);//散列的次数，默认1次， 设置两次相当于 md5(md5(""));
		return hashedCredentialsMatcher;
	}

	@Bean(name = "shiroFilter")
/*	@DependsOn("securityManager")
	@ConditionalOnMissingBean*/
	public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
		/*securityManager.setRealm(realm);*/
		ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		shiroFilter.setSecurityManager(securityManager);
		/**不设置默认自动找默认目录下的login.ftl **/
		shiroFilter.setLoginUrl(loginUrl);
		/**没有权限操作时跳转的页面 **/
		shiroFilter.setUnauthorizedUrl("/error/404");
		LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		/**anon匿名访问**/
		filterChainDefinitionMap.put("/login", "anon");
		// 退出 logout地址，shiro去清除session
		filterChainDefinitionMap.put("/logout", "logout");
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/templates/**", "authc");
		//  菜单列
		List<SysMenuEntity> list = sysMenuService.findAll(SysMenuEntity.class);
		if (StringUtils.isNotEmpty(list)) {
			for (SysMenuEntity menu : list) {
				filterChainDefinitionMap.put(menu.getUrl(), "perms[" + menu.getPerms() + "]");
			}
		}

		Map<String, Filter> filters = new LinkedHashMap<>();

		filters.put("onlineSession", onlineSessionFilter());
		filters.put("syncOnlineSession", syncOnlineSessionFilter());
		filterChainDefinitionMap.put("/**", "onlineSession,syncOnlineSession");
		// 注销成功，则跳转到指定页面
		filters.put("logout", logoutFilter());
		shiroFilter.setFilters(filters);
	   /**注入到拦截器里**/
		shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilter;
	}

	/**
	 * 自定义在线用户处理过滤器
	 */
	@Bean
	public OnlineSessionFilter onlineSessionFilter()
	{
		OnlineSessionFilter onlineSessionFilter = new OnlineSessionFilter();
		return onlineSessionFilter;
	}

	/**
	 * 自定义在线用户同步过滤器
	 */
	@Bean
	public SyncOnlineSessionFilter syncOnlineSessionFilter()
	{
		SyncOnlineSessionFilter syncOnlineSessionFilter = new SyncOnlineSessionFilter();
		return syncOnlineSessionFilter;
	}

	/**
	 * 退出过滤器
	 */
	public LogoutFilter logoutFilter()
	{
		LogoutFilter logoutFilter = new LogoutFilter();
		return logoutFilter;
	}


}
